#include "../Socket.h"
#include <netinet/tcp.h>
using namespace yhaida;

void Socket::bind(const InetAddress &addr)
{
    sockets::bindOrDie(_fd, addr.getSockAdrrInet());
}

void Socket::listen()
{
    sockets::listenOrDie(_fd);
}

int Socket::accept(InetAddress *peeraddr)
{
    struct sockaddr_in addr;
    bzero(&addr, sizeof(addr));
    int connfd = sockets::accept(_fd, &addr);
    if (connfd >= 0)
    {
        peeraddr->setSockAddrInet(addr);
    }
    return connfd;
}

void Socket::setReuseAdr(bool on)
{
    int optval = on ? 1 : 0;
    ::setsockopt(_fd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval));
}
void Socket::setReusePort(bool on)
{
#ifdef SO_REUSEPORT
    int optval = on ? 1 : 0;
    int ret = ::setsockopt(_fd, SOL_SOCKET, SO_REUSEPORT,
                           &optval, static_cast<socklen_t>(sizeof optval));
    if (ret < 0 && on)
    {
        LOG_SYSERR << "SO_REUSEPORT failed.";
    }
#else
    if (on)
    {
        LOG_ERROR << "SO_REUSEPORT is not supported.";
    }
#endif
}

void Socket::shutdownWrite()
{
    sockets::shutdownWrite(_fd);
}

void Socket::setTcpNoDelay(bool on)
{
    int optval = on ? 1 : 0;
    ::setsockopt(_fd, IPPROTO_TCP, TCP_NODELAY,
                 &optval, sizeof optval);
}

void Socket::setTcpKeepAlive(bool on)
{
    int keepAlive = 1; //开启keepalive属性,缺省值:0(关闭)
    // int keepIdle = 5;     //如果在5秒内没有任何数据交互,则进行探测,缺省值:7200(s)
    // int keepInterval = 2; //探测时发探测包的时间间隔为2秒,缺省值:75(s)
    // int keepCount = 2;    //探测重试的次数,全部超时则认定连接失效,缺省值:9(次)
    setsockopt(_fd, SOL_SOCKET, SO_KEEPALIVE, (void *)&keepAlive, sizeof(keepAlive));
    // setsockopt(_fd, SOL_TCP, TCP_KEEPIDLE, (void *)&keepIdle, sizeof(keepIdle));
    // setsockopt(_fd, SOL_TCP, TCP_KEEPINTVL, (void *)&keepInterval, sizeof(keepInterval));
    // setsockopt(_fd, SOL_TCP, TCP_KEEPCNT, (void *)&keepCount, sizeof(keepCount));
}